#ifndef __rtspRecver_H__
#define __rtspRecver_H__
#include <time.h>
#include <string>
#include <map>
#include <list>
#include <netinet/in.h>
#include "baseSession.h"
#include "fileParser.h"
#include <sys/epoll.h>
#include <sys/timerfd.h>
using namespace std;

#define MTU 1386
#define RTPHEADER_LEN 12

#define VIDEOTRACK 0
#define AUDIOTRACK 1

#define SERVERNAME "c-rtsp_server"

typedef struct _RtpHeader
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
	/* byte 0 */
	unsigned char csrc_count : 4;
	unsigned char extension : 1;
	unsigned char padding : 1;
	unsigned char version : 2;
	/* byte 1 */
	unsigned char payload_type : 7;
	unsigned char marker : 1;
#else
	/* byte 0 */
	unsigned char marker : 1;
	unsigned char payload_type : 7;
	/* byte 1*/
	unsigned char version : 2;
	unsigned char padding : 1;
	unsigned char extension : 1;
	unsigned char csrc_count : 4;
#endif
	/* bytes 2,3 */
	unsigned short seq;
	/* bytes 4-7 */
	unsigned int timestamp;
	/* bytes 8-11 */
	unsigned int ssrc;

	_RtpHeader()
	{
		csrc_count = 0;
		extension = 0;
		padding = 0;
		version = 2;
		marker = 0;
		timestamp = 0;
		seq = 0;
	}
} RtpHeader;

typedef struct _RtcpHeader
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
	/* byte 0*/
	unsigned char rc : 5;
	unsigned char padding : 1;
	unsigned char version : 2;
#else
	unsigned char version : 2;
	unsigned char padding : 1;
	unsigned char rc : 5;
#endif
	/* byte 1*/
	unsigned char pt;
	/* byte 2-3*/
	unsigned short length;
	unsigned int ssrc;
	unsigned int ntp_ts_high32;
	unsigned int ntp_ts_low32;
	unsigned int rtp_ts;
	unsigned int send_packet_count;
	unsigned int send_bytes_count;

	_RtcpHeader()
	{
		rc = 0;
		padding = 0;
		version = 2;
		pt = 200; // sr
		length = htons(6);
		rtp_ts = 0;
		send_packet_count = 0;
		send_bytes_count = 0;
	}

} RtcpHeader;
#pragma pack(push, 1) 
typedef struct _SDESHeader
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
	/* byte 0*/
	unsigned char rc : 5;
	unsigned char padding : 1;
	unsigned char version : 2;
#else
	unsigned char version : 2;
	unsigned char padding : 1;
	unsigned char rc : 5;
#endif
	/* byte 1*/
	unsigned char pt;
	/* byte 2-3*/
	unsigned short length;
	unsigned int ssrc;
	unsigned char cname;
	unsigned char cname_len;
	char text[strlen(SERVERNAME)];
	unsigned char cname_type;

	_SDESHeader()
	{
		rc = 1;
		padding = 0;
		version = 2;
		pt = 202; // sr
		cname = 1;
		cname_len = strlen(SERVERNAME);
		memcpy(text, SERVERNAME, strlen(SERVERNAME));
		cname_type = 0;

		length= htons(5);
	}
} SDESHeader;
#pragma pack(pop)

typedef struct _TRACK
{
	int local_rtp_port;
	int local_rtcp_port;
	int peer_rtp_port;
	int peer_rtcp_port;
	int rtp_fd;
	int rtcp_fd;
	_TRACK()
	{
		rtp_fd = -1;
		rtcp_fd = -1;
	}

} Track;

class RtcpSession : public BaseSession
{
public:
	RtcpSession()
	{
		return;
	}
	~RtcpSession()
	{
		return;
	}
	int rtp_fd = -1; // rtp fd
	int send_rtcp();
	void send_sdes();
};

class RtpSession : public BaseSession
{
public:
	RtpSession()
	{
		read_timer = timerfd_create(CLOCK_MONOTONIC, 0);
		return;
	}
	~RtpSession();
	
	RtpHeader rtp_header; // rtp header
	bool is_video = false;
	bool av_seek = false;
	bool is_pause = false;
	int rtcp_fd = -1;
	int read_timer = -1;	// 读取文件timer
	float start_time;
	int read_file_data(int fd);

	int start_read_timer(int delay, int delay_ns, int to, int to_ns);
private:
	FileParser file_reader;
	
	int send_video(AVPacket *packet, bool is_last, int64_t start_pts);
	int send_audio(AVPacket *packet, bool is_last, int64_t start_pts);
	int single_nalu(unsigned char *data, int len);
	int fu_a_h264(unsigned char *data, int len);
	int fu_a_h265(unsigned char *data, int len);
	int aac_transform_rtp(unsigned char *data, int len, int pts);
	int video_transform_rtp(unsigned char *data, int len, int pts); // rtp封装h264
	void clear_cache();

	list<AVPacket *> packets_cache;

	unsigned int seq = 0; // rtp header中的seq

	unsigned int send_bytes_count = 0;
	unsigned int send_packets_count = 0;

	friend class RtspSession;
	friend class RtcpSession;
};

class RtspSession : public BaseSession
{
public:
	RtspSession()
	{
		func_map["OPTIONS"] = &handle_options;
		func_map["DESCRIBE"] = &handle_describe;
		func_map["SETUP"] = &handle_setup;
		func_map["TEARDOWN"] = &handle_teardown;
		func_map["PLAY"] = &handle_play;
		func_map["GET_PARAMETER"] = &handle_getpar;
		func_map["PAUSE"] = &handle_pause;
	}
	~RtspSession()
	{

		func_map.clear();
	}

	int read_rtsp_data(); // 读取信令

	int handle_options(const char *buff);
	int handle_describe(const char *buff);
	int handle_setup(const char *buff);
	int handle_teardown(const char *buff);
	int handle_play(const char *buff);
	int handle_getpar(const char *buff);
	int handle_pause(const char *buff);
	bool start_send_media_data = false;
	string get_sdp()
	{
		return sdp;
	}

	int get_fd()
	{
		return sock_fd;
	}

	string get_session_id()
	{
		return sessionid;
	}

	void set_session_id(string _sessionid)
	{
		sessionid = _sessionid;
	}

	Track tracks[2];
	int start_read_timer(int delay, int delay_ns, int to, int to_ns); // 开启定时器，读文件
	int read_file_data(int fd);										  // 读取文
	int send_rtsp_resp(int code, string status, string extra_data = "");
private:
	int create_rtp_rtcp_session(int id);
	string make_sdp();
	string getcseq(const char *data);
	
	string cseq = "";
	string sdp = "";
	string sessionid = "";
	string sps = "";
	string pps = "";
	string vps = "";
	FileParser file_parser;
	std::map<string, int (RtspSession::*)(const char *buff)> func_map;
};

#define GET(var) ((static_cast<BaseSession*>(events[fd]->session_handler))->var)
#define RTSP(var) ((static_cast<RtspSession*>(events[fd]->session_handler))->var)
#define RTP(var) ((static_cast<RtpSession*>(events[fd]->session_handler))->var)
#define RTCP(var) ((static_cast<RtcpSession*>(events[fd]->session_handler))->var)
#endif
